package org.breathe.rdb;

import lombok.extern.slf4j.Slf4j;
import org.breathe.server.core.RedisCore;

import java.io.*;

/**
 * @author: breathe
 * @createTime: 2025-06-09
 */
@Slf4j
public class RdbLoader {
    private RedisCore redisCore;
    public RdbLoader(RedisCore redisCore) {
        this.redisCore = redisCore;
    }

    public boolean loadRdb(File file) {
        if (!file.exists()) {
            log.info("RDB file is not exists: {}", file.getAbsoluteFile());
            return true;
        }
        try (DataInputStream dis = new DataInputStream(new BufferedInputStream(new FileInputStream(file)))) {
            //check header
            if (!RdbUtils.checkRdbHeader(dis)) {
                log.info("RDB file header error");
                return false;
            }
            //read db
            loadAllDatabases(dis);
        } catch (Exception e) {
            log.error("RDB file load fail", e);
            return false;
        }
        return false;
    }

    private void loadAllDatabases(DataInputStream dis) throws IOException {
        int currentDbIndex = 0;
        while (true) {
            int type = dis.read();
            if (type == -1 || (byte)type == RdbConstants.RDB_OPCODE_EOF) {
                break;
            }
            switch ((byte)type) {
                case RdbConstants.RDB_OPCODE_SELECT_DB:
                    currentDbIndex = dis.read();
                    redisCore.selectDB(currentDbIndex);
                    log.info("choose db: {}", currentDbIndex);
                    break;
                case RdbConstants.STRING_TYPE:
                    RdbUtils.loadString(dis, redisCore, currentDbIndex);
                    break;
                case RdbConstants.LIST_TYPE:
                    RdbUtils.loadList(dis, redisCore, currentDbIndex);
                    break;
                case RdbConstants.SET_TYPE:
                    RdbUtils.loadSet(dis, redisCore, currentDbIndex);
                    break;
                case RdbConstants.HASH_TYPE:
                    RdbUtils.loadHash(dis, redisCore, currentDbIndex);
                    break;
                case RdbConstants.ZSET_TYPE:
                    RdbUtils.loadZSet(dis, redisCore, currentDbIndex);
                    break;
                default:
                    log.warn("no support type: {}", type);
                    break;
            }
        }
    }
}
